﻿namespace WatiNSahi.Extensions
{
    using System;
    using System.Text;
    using global::WatiN.Core;


    public static class Assert
    {
        public static bool AreEqual(string expectedValue, string actualValue, string message )
        {
            bool result = false;
            if (expectedValue.Equals(actualValue))
            {
                result = true;
                Console.WriteLine(string.Format("Assert equals returns true. Expected value : '{0}' is equal to actual value : '{1}'.",
                    expectedValue, actualValue));
            }
            return result;

        }

        internal static void AreEqual(bool expected, bool actual, string message)
        {
            if(expected.Equals(actual))
            {
                Console.WriteLine("Assert AreEqual : Expected value and Actual Value are equal");
            }
            else
            {
                Console.WriteLine(string.Format("Assert AreEqual : Expected value and Actual Value are NOT equal. Message :: '{0}'", message));
            }

        }

        internal static void IsTrue(bool condition, string message)
        {
            if(condition != true)
            {
                Console.WriteLine(string.Format("Assert IsTrue returns false. Message :: '{0}'",message));
            }
            else
            {
                Console.WriteLine("Assert IsTrue returns true.");
            }
                
        }
    }

    public static class BrowserExtensions
    {
        /// <summary>
        /// Fires JS Event. Note: jQuery may be required to fire selected event.
        /// </summary>
        /// <typeparam name="TJSEvent">JS Event</typeparam>
        /// <param name="browser">Browser</param>
        /// <param name="parameters">Event parameters</param>
        public static void FireJSEventByParameters<TJSEvent>(this Browser browser, params string[] parameters) where TJSEvent : IJSEvent, new()
        {
            var @event = new TJSEvent();

            browser.Eval(string.Format(@event.ByParameters, parameters));
        }

        /// <summary>
        /// Fires JS Event. Note: jQuery may be required to fire selected event.
        /// </summary>
        /// <typeparam name="TJSEvent">JS Event</typeparam>
        /// <param name="browser">Browser</param>
        /// <param name="elementId">ID of the element on which event will be fired</param>
        public static void FireJSEvent<TJSEvent>(this Browser browser, string elementId) where TJSEvent : IJSEvent, new()
        {
            var @event = new TJSEvent();

            browser.Eval(string.Format(@event.ById, elementId));
        }

        /// <summary>
        /// Fires JS Event. Note: jQuery may be required to fire selected event.
        /// </summary>
        /// <typeparam name="TJSEvent">JS Event</typeparam>
        /// <param name="browser">Browser</param>
        /// <param name="elementClass">Class of the element on which event will be fired</param>
        public static void FireJSEventByClass<TJSEvent>(this Browser browser, string elementClass) where TJSEvent : IJSEvent, new()
        {
            var @event = new TJSEvent();

            browser.Eval(string.Format(@event.ByClass, elementClass));
        }

        /// <summary>
        /// Evaluates "jQuery('#textFieldId').val('text');". Note: jQuery is required to fire selected event.
        /// </summary>
        /// <param name="browser"></param>
        /// <param name="textFieldId"></param>
        /// <param name="text"></param>
        public static void SetTextUsingJS(this Browser browser, string textFieldId, string text)
        {
            browser.Eval(string.Format("jQuery('#{0}').val('{1}');", textFieldId, text));
        }

        /// <summary>
        /// Evaluates "jQuery('.textFieldClass').val('text');". Note: jQuery is required to fire selected event.
        /// </summary>
        /// <param name="browser"></param>
        /// <param name="textFieldClass"></param>
        /// <param name="text"></param>
        public static void SetTextByClassUsingJS(this Browser browser, string textFieldClass, string text)
        {
            browser.Eval(string.Format("jQuery('.{0}').val('{1}');", textFieldClass, text));
        }

        /// <summary>
        /// Get element by its XPath.
        /// </summary>
        /// <typeparam name="TElement">Element</typeparam>
        /// <param name="browser">Browser</param>
        /// <param name="xpath">Xpath</param>
        /// <returns>Element identified by <paramref name="xpath"/></returns>
        public static TElement GetByXPath<TElement>(this Browser browser, string xpath) where TElement : Element
        {
            string injectJavascriptXPath =
                    @"var script=document.createElement('script');" +
                    @"script.src='http://svn.coderepos.org/share/lang/javascript/javascript-xpath/trunk/release/javascript-xpath-latest-cmp.js';" +
                    @"script.type='text/javascript';" +
                    @"document.getElementsByTagName('head')[0].appendChild(script);";
            browser.Eval(injectJavascriptXPath);

            string elementId = Guid.NewGuid().ToString();
            StringBuilder js = new StringBuilder();
            js.Append(@"function getId(){var result = document.evaluate('" + xpath.Replace("'", "\"") + "', document, null, 7, null);");
            js.Append(@"var ele = result.snapshotItem(0);");
            js.Append(@"if (ele.id.length > 0) {return ele.id;} else {ele.setAttribute('id', '" + elementId + "'); return '" + elementId + "';}}getId();");
            elementId = browser.Eval(js.ToString());

            return browser.Get<TElement>(elementId);
        }
    }
}
